﻿#include "netif_pacp.h"
#include "sys_plat.h"
#include "exmsg.h"
#include "ether.h"

/**
 * @brief 网卡接受消息线程
 */
void recv_thread(void *arg)
{
    netif_t *netif = (netif_t *)arg;
    pcap_t *pcap_data = (pcap_t *)netif->ops_data;

    // 接受物理机传输过来的数据
    while (1)
    {
        // 接收收到的数据
        struct pcap_pkthdr *pkthdr = NULL;
        const uint8_t *pkt_data = NULL;
        if (pcap_next_ex(pcap_data, &pkthdr, &pkt_data) != 1)
        {
            continue;
        }

        // 处理收到的数据
        pktbuf_t *buf = pktbuf_alloc(pkthdr->len);
        if (!buf)
        {
            DBG_WARNING(DBG_NETIF_PCAP_LEVEL, "alloc pktbuf failed!");
            continue;
        }

        pktbuf_reset_acc(buf);
        pktbuf_write(buf, pkt_data, pkthdr->len);

        if (netif_put_in(netif, buf, DELIVER_NO_WAITTIME) < NET_ERR_OK)
        {
            DBG_WARNING(DBG_NETIF_PCAP_LEVEL, "put buf in inq failed!");
            pktbuf_free(buf);
            continue;
        }
    }
}

/**
 * @brief 网卡发送消息线程
 */
void send_thread(void *arg)
{
    netif_t *netif = (netif_t *)arg;
    pcap_t *pcap = (pcap_t *)netif->ops_data;
    int buffer_size = ETHER_MTU + sizeof(ether_hdr_t);
    static uint8_t rw_buffer[ETHER_MTU + 6 + 6 + 2];

    while (1)
    {
        pktbuf_t *buf = netif_get_out(netif, -1);
        if (!buf)
        {
            continue;
        }

        int total_size = buf->total_size;
        pktbuf_reset_acc(buf);
        plat_memset(rw_buffer, 0, buffer_size);
        pktbuf_read(buf, rw_buffer, total_size, buffer_size);
        pktbuf_free(buf);
        if (pcap_inject(pcap, rw_buffer, total_size) == -1)
        {
            DBG_ERROR(DBG_NETIF_LEVEL, "pcap send pkt failed:%s!", pcap_geterr(pcap));
            DBG_ERROR(DBG_NETIF_PCAP_LEVEL, "pkt send faied size:%d\n", total_size);
            continue;
        }
        DBG_INFO(DBG_NETIF_PCAP_LEVEL, "netif:%s send a msg!", netif->name);
    }
}

/**
 * @brief 开启网络接口相关操作
 * @param netif 网络接口
 * @param data 主要是地址相关,用于npcap打开网卡
 */
static net_err_t netif_pcap_open(netif_t *netif, void *data)
{
    pcap_data_t *pcap_data = (pcap_data_t *)data;
    pcap_t *pcap = pcap_device_open(pcap_data->ip, pcap_data->hwaddr);
    if (!pcap)
    {
        DBG_ERROR(DBG_NETIF_PCAP_LEVEL, "open pcap device failed!");
        return NET_ERR_SYS;
    }

    // 设置网络接口相关参数
    netif->type = NETIF_TYPE_ETHER;
    netif->mtu = ETHER_MTU;
    netif->ops_data = pcap;
    netif_set_hwaddr(netif, pcap_data->hwaddr, 6);

    sys_thread_create(recv_thread, netif);
    sys_thread_create(send_thread, netif);

    return NET_ERR_OK;
}

static net_err_t netif_pcap_close(netif_t *netif)
{
    pcap_t *pcap = (pcap_t *)netif->ops_data;
    pcap_close(pcap);
    return NET_ERR_OK;
}

static net_err_t netif_pcap_xmit(netif_t *netif)
{

    return NET_ERR_OK;
}

const netif_ops_t netdev_ops = {
    .open = netif_pcap_open,
    .close = netif_pcap_close,
    .xmit = netif_pcap_xmit};
